package com.gexing.jsondemo.ui;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;

import org.json.JSONArray;
import org.json.JSONObject;

import android.util.DebugUtils;

public class BeanUtils {
	public static final String CLASSNAME_STRING = "java.lang.String";
	public static final String CLASSNAME_INT = "int";
	public static final String CLASSNAME_LONG = "long";
	public static final String CLASSNAME_BYTE = "byte";
	public static final String CLASSNAME_CHAR = "char";
	public static final String CLASSNAME_DOUBLE = "double";
	public static final String CLASSNAME_FLOAT = "float";
	public static final String CLASSNAME_BOOLEAN = "boolean";
	public static final String CLASSNAME_ARRAY = "java.util.ArrayList";

	public static <T> T jsonObjectToBean(Class<T> clazz, JSONObject jsonObject) {
		try {
			T newInstance = clazz.newInstance();
			Iterator keys = jsonObject.keys();
			while (keys.hasNext()) {
				String key = (String) keys.next();
				Field name = clazz.getDeclaredField(key);
				name.setAccessible(true);
				String className = name.getType().getName().trim();
				if (CLASSNAME_STRING.equals(className)) {
					name.set(newInstance, jsonObject.getString(key));
				} else if (CLASSNAME_INT.equals(className)) {
					name.setInt(newInstance, jsonObject.getInt(key));
				} else if (CLASSNAME_LONG.equals(className)) {
					name.setLong(newInstance, jsonObject.getLong(key));
				} else if (CLASSNAME_BOOLEAN.equals(className)) {
					name.setBoolean(newInstance, jsonObject.getBoolean(key));
				} else if (CLASSNAME_ARRAY.equals(className)) {
					String genericsTypeName = ((BaseModel) newInstance).getGenericsTypeName(key);
					JSONArray jsonArray = jsonObject.getJSONArray(key);
					ArrayList array = new ArrayList();
					if (StringUtils.isBaseDataType(genericsTypeName)) {
						for (int i = 0; i < jsonArray.length(); i++) {
							array.add(jsonArray.get(i));
						}
					} else {
						for (int i = 0; i < jsonArray.length(); i++) {
							array.add(jsonObjectToBean(Class.forName(genericsTypeName), jsonArray.getJSONObject(i)));
						}
					}
					name.set(newInstance, array);
				} else {
					if (StringUtils.isNotBlank(jsonObject.get(key) + "")) {
						name.set(newInstance, jsonObjectToBean(Class.forName(className), jsonObject.getJSONObject(key)));
					}
				}
			}
			return newInstance;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static <T> JSONObject beanToJsonObject(T t) {
		try {
			JSONObject jo = new JSONObject();
			Class clazz = t.getClass();
			Field[] fields = clazz.getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				Field field = fields[i];
				field.setAccessible(true);
				String name = field.getName();
				String className = field.getType().getName().trim();
				if (CLASSNAME_STRING.equals(className)) {
					jo.put(name, field.get(t));
				} else if (CLASSNAME_INT.equals(className)) {
					jo.put(name, field.getInt(t));
				} else if (CLASSNAME_LONG.equals(className)) {
					jo.put(name, field.getLong(t));
				} else if (CLASSNAME_BOOLEAN.equals(className)) {
					jo.put(name, field.getBoolean(t));
				} else if (CLASSNAME_ARRAY.equals(className)) {
					String genericsTypeName = ((BaseModel) t).getGenericsTypeName(name);
					JSONArray jsonArray = new JSONArray();
					ArrayList array = (ArrayList) field.get(t);
					for (int j = 0; j < array.size(); j++) {
						if (StringUtils.isBaseDataType(genericsTypeName)) {
							jsonArray.put(array.get(j));
						} else {
							jsonArray.put(beanToJsonObject(array.get(j)));
						}

					}
					jo.put(name, jsonArray);
				} else {
					jo.put(name, beanToJsonObject(field.get(t)));
				}

			}
			return jo;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}
